package cn.ultrarisk.scadmin.manager.biz.stat.service;

import cn.ultrarisk.mybatis.extension.query.Query;
import cn.ultrarisk.scadmin.manager.biz.monitor.dao.SolrCacheMonitorDAO;
import cn.ultrarisk.scadmin.manager.biz.monitor.dao.SolrReplicaMonitorDAO;
import cn.ultrarisk.scadmin.manager.biz.monitor.entity.SolrCacheMonitor;
import cn.ultrarisk.scadmin.manager.biz.monitor.entity.SolrReplicaMonitor;
import cn.ultrarisk.scadmin.manager.biz.solr.context.SolrState;
import cn.ultrarisk.scadmin.manager.biz.stat.context.StatType;
import cn.ultrarisk.scadmin.manager.biz.stat.dao.SolrReplicaStatDAO;
import cn.ultrarisk.scadmin.manager.biz.stat.entity.SolrReplicaStat;
import cn.ultrarisk.scadmin.manager.util.CollectionUtil;
import cn.ultrarisk.scadmin.manager.util.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * solr副本统计数据操作类
 *
 * @author sevendlong(lin23871@163.com)
 * @date 2014/3/28
 * @since V1.0
 */
@Service
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public class SolrReplicaStatService {
    @Autowired
    private SolrReplicaStatDAO solrReplicaStatDAO;
    @Autowired
    private SolrReplicaMonitorDAO solrReplicaMonitorDAO;
    @Autowired
    private SolrCacheMonitorDAO solrCacheMonitorDAO;

    /**
     * 构建小时粒度的统计数据
     *
     * @query time
     */
    public void buildHourStat(long time) {
        long startTime = DateUtil.getHourBeginTime(time);
        long endTime = DateUtil.getHourEndTime(time);

        List<SolrReplicaMonitor> growStat = solrReplicaMonitorDAO.getGrowStat(startTime, endTime);
        Map<SolrReplicaMonitor, Map<String, Integer>> statusStat = solrReplicaMonitorDAO.getStatusStat(startTime, endTime);
        Map<SolrCacheMonitor, Double> cacheStat = solrCacheMonitorDAO.getCacheStat(startTime, endTime);
        Map<SolrCacheMonitor, Map<String, Double>> qpsStat = solrCacheMonitorDAO.getQPSStat(startTime, endTime);
        Map<SolrCacheMonitor, Long> visitStat = solrCacheMonitorDAO.getVisitCount(startTime, endTime);

        Map<Integer, SolrReplicaStat> statMap = new HashMap<Integer, SolrReplicaStat>();
        if (growStat != null) {
            for (SolrReplicaMonitor monitor : growStat) {
                SolrReplicaStat stat = statMap.get(monitor.getReplicaId());
                if (stat == null) {
                    stat = new SolrReplicaStat();
                    stat.setNodeId(monitor.getNodeId());
                    stat.setCollectionId(monitor.getCollectionId());
                    stat.setShardId(monitor.getShardId());
                    stat.setReplicaId(monitor.getReplicaId());
                }
                stat.setDocs(monitor.getNumDocs());
                statMap.put(stat.getReplicaId(), stat);
            }
        }
        if (statusStat != null) {
            for (SolrReplicaMonitor monitor : statusStat.keySet()) {
                SolrReplicaStat stat = statMap.get(monitor.getReplicaId());
                if (stat == null) {
                    stat = new SolrReplicaStat();
                    stat.setNodeId(monitor.getNodeId());
                    stat.setCollectionId(monitor.getCollectionId());
                    stat.setShardId(monitor.getShardId());
                    stat.setReplicaId(monitor.getReplicaId());
                }
                Map<String, Integer> replicaStatusMap = statusStat.get(monitor);
                for (String stateKey : replicaStatusMap.keySet()) {
                    Integer stateVal = replicaStatusMap.get(stateKey);
                    if ("ALL".equals(stateKey)) {
                        stat.setState(stateVal);
                    } else if (SolrState.LEADER.toString().equals(stateKey)) {
                        stat.setLeaderState(stateVal);
                    } else if (SolrState.ACTIVE.toString().equals(stateKey)) {
                        stat.setActiveState(stateVal);
                    } else if (SolrState.RECOVERING.toString().equals(stateKey)) {
                        stat.setRecoveringState(stateVal);
                    } else if (SolrState.DOWN.toString().equals(stateKey)) {
                        stat.setDownState(stateVal);
                    } else if (SolrState.RECOVERY_FAILED.toString().equals(stateKey)) {
                        stat.setRecoverFailedState(stateVal);
                    } else if (SolrState.GONE.toString().equals(stateKey)) {
                        stat.setGoneState(stateVal);
                    }
                }
                statMap.put(stat.getReplicaId(), stat);
            }
        }
        if (cacheStat != null) {
            for (SolrCacheMonitor monitor : cacheStat.keySet()) {
                SolrReplicaStat stat = statMap.get(monitor.getReplicaId());
                if (stat == null) {
                    stat = new SolrReplicaStat();
                    stat.setNodeId(monitor.getNodeId());
                    stat.setCollectionId(monitor.getCollectionId());
                    stat.setShardId(monitor.getShardId());
                    stat.setReplicaId(monitor.getReplicaId());
                }
                stat.setHits(cacheStat.get(monitor));
                statMap.put(stat.getReplicaId(), stat);
            }
        }
        if (qpsStat != null) {
            for (SolrCacheMonitor monitor : qpsStat.keySet()) {
                SolrReplicaStat stat = statMap.get(monitor.getReplicaId());
                if (stat == null) {
                    stat = new SolrReplicaStat();
                    stat.setNodeId(monitor.getNodeId());
                    stat.setCollectionId(monitor.getCollectionId());
                    stat.setShardId(monitor.getShardId());
                    stat.setReplicaId(monitor.getReplicaId());
                }
                Map<String, Double> monitorQpsMap = qpsStat.get(monitor);
                if (monitorQpsMap != null) {
                    stat.setAvgQps(monitorQpsMap.get("avg"));
                    stat.setMaxQps(monitorQpsMap.get("max"));
                }
                if (visitStat != null) {
                    stat.setVisitCount(visitStat.get(monitor));
                }
                statMap.put(stat.getReplicaId(), stat);
            }
        }

        if (statMap.size() > 0) {
            for (SolrReplicaStat stat : statMap.values()) {
                stat.setType(StatType.HOUR);
                stat.setStartTime(startTime);
                stat.setEndTime(endTime);
            }
            solrReplicaStatDAO.createBatch(statMap.values());
        }
    }

    public void deleteHourStat(long time) {
        Query query = Query.query(SolrReplicaStat.TYPE, StatType.HOUR)
                .gte(SolrReplicaStat.START_TIME, DateUtil.getHourBeginTime(time)).lt(SolrReplicaStat.START_TIME, DateUtil.getHourEndTime(time));
        solrReplicaStatDAO.delete(query);
    }

    public void buildDayStat(long time) {
        long startTime = DateUtil.getDayBeginTime(time);
        long endTime = DateUtil.getDayEndTime(time);
        List<SolrReplicaStat> stats = solrReplicaStatDAO.buildStat(startTime, endTime);
        if (CollectionUtil.isNotEmpty(stats)) {
            for (SolrReplicaStat stat : stats) {
                stat.setType(StatType.DAY);
            }
            solrReplicaStatDAO.createBatch(stats);
        }
    }

    public void deleteDayStat(long time) {
        Query query = Query.query(SolrReplicaStat.TYPE, StatType.DAY)
                .gte(SolrReplicaStat.START_TIME, DateUtil.getDayBeginTime(time)).lt(SolrReplicaStat.START_TIME, DateUtil.getDayEndTime(time));
        solrReplicaStatDAO.delete(query);
    }

    public void buildMonthStat(long time) {
        long startTime = DateUtil.getMonthBeginTime(time);
        long endTime = DateUtil.getMonthEndTime(time);

        List<SolrReplicaStat> stats = solrReplicaStatDAO.buildStat(startTime, endTime);
        if (CollectionUtil.isNotEmpty(stats)) {
            for (SolrReplicaStat stat : stats) {
                stat.setType(StatType.MONTH);
            }
            solrReplicaStatDAO.createBatch(stats);
        }
    }

    public void deleteMonthStat(long time) {
        Query query = Query.query(SolrReplicaStat.TYPE, StatType.MONTH)
                .gte(SolrReplicaStat.START_TIME, DateUtil.getMonthBeginTime(time)).lt(SolrReplicaStat.START_TIME, DateUtil.getMonthEndTime(time));
        solrReplicaStatDAO.delete(query);
    }
}